package com.ms.service.module.account;

import java.util.ArrayList;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.infinispan.util.concurrent.ConcurrentHashSet;

import com.ms.service.module.broadcastlistener.LoginLogoutListener;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.service.module.common.PlayerCommonInfoManager;

/**
 * 體驗帳號管理員
 */
public class TrialAccountManager {

	private static final Log log = LogFactory.getLog(TrialAccountManager.class);

	/**
	 * accountModule實體
	 */
	private AccountModule ownModule;
	public void setOwnModule(AccountModule module){
		if(module != null){
			this.ownModule = module;			
		}
	}
	
	/**
	 * 成功取出的帳號<br>
	 * key:accountID<br>
	 * value:playerGUID(該體驗帳號的第一隻角色GUID)
	 */
	private ConcurrentHashMap<GUID, GUID> lendOutAccountMap = new ConcurrentHashMap<GUID, GUID>();
	
	/**
	 * 從login傳回來成功登入的帳號
	 */
	private ConcurrentHashSet<GUID> loginSuccessAccounts = new ConcurrentHashSet<GUID>();
	
	/**
	 * 待觀察的帳號，這邊會放入當timmer觸發時有可能還在進行登入流程的帳號
	 */
	private ArrayList<GUID> checkAcccounts = new ArrayList<GUID>();
	
	/**
	 * 新增一個[成功取出]的帳號與角色
	 */
	public void addLendOutPlayer(GUID accountID, GUID playerGUID){
		if(accountID == null || playerGUID == null){
			return;
		}
		
		lendOutAccountMap.put(accountID, playerGUID);
		
		//同時也要收聽這隻角色成功登入的消息
		LoginLogoutListener.addLogInPlayerListener(ownModule, playerGUID);
	}
	
	/**
	 * 依據帳號移除一個[成功取出]的角色
	 */
	public void removeLendOutPlayer(GUID accountID){
		if(accountID == null){
			return;
		}
		
		GUID playerGUID = lendOutAccountMap.remove(accountID);
		if(playerGUID == null){
			if(log.isErrorEnabled()){
				log.error("["+ownModule.getModuleName()+"] removeLendOutPlayer fail, accountID:"+accountID.toString());
			}
		}
	}
	
	/**
	 * 新增一個[登入成功]的帳號
	 */
	public void addLoginSuccessAccount(GUID accountID){
		if(accountID == null){
			return;
		}
		
		loginSuccessAccounts.add(accountID);
		
		//如果待觀察裡面有自己，就移除
		if(checkAcccounts.contains(accountID)){
			checkAcccounts.remove(accountID);
		}
	}
	
	/**
	 * 移除一個[登入成功]的帳號
	 */
	public void removeLoginSuccessAccount(GUID accountID){
		if(accountID == null){
			return;
		}
		
		boolean result = loginSuccessAccounts.remove(accountID);
		if(!result){
			if(log.isErrorEnabled()){
				log.error("["+ownModule.getModuleName()+"] removeLoginSuccessAccount fail, accountID:"+accountID.toString());
			}
		}
		
		//如果待觀察裡面有自己，就移除
		if(checkAcccounts.contains(accountID)){
			checkAcccounts.remove(accountID);
		}
	}
	
	/**
	 * timmer觸發時執行<br>
	 * 檢查成功取出的角色是否都有成功登入，回傳一個沒有成功登入的帳號List
	 */
	public ArrayList<GUID> checkLendOutAccounts(){
		
		//結果可用的帳號
		ArrayList<GUID> resultAccountIDs = new ArrayList<GUID>();
		
		//對觀察中的帳號
		for(GUID accountID : checkAcccounts){
			GUID playerGUID = lendOutAccountMap.get(accountID);
			GUID sessionID = PlayerCommonInfoManager.getInstance().getSessionByPlayerGuid(playerGUID);
			
			//帳號角色不在線上
			if(sessionID == null){
				resultAccountIDs.add(accountID);
			}
			//帳號角色在線上
			else{
				//這邊有可能是登入廣播沒送到
				if(log.isWarnEnabled()){
					log.warn("["+ownModule.getModuleName()+"] may not receive character login notify, accountID:"+accountID.toString()+", playerGUID:"+playerGUID.toString());
				}
				
				//自動加入登入成功帳號
				loginSuccessAccounts.add(accountID);
				
				//去刪掉收聽登入廣播
				LoginLogoutListener.removeLogInPlayerListener(ownModule, playerGUID);
			}
		}
		
		//加入後馬上clear，這次執行完會再整理一份新的
		checkAcccounts.clear();

		
		//對每個成功借出的帳號
		for(Entry<GUID, GUID> entry : lendOutAccountMap.entrySet()){
			GUID accountID = entry.getKey();
			
			//如果成功登入的帳號裡面有了，檢查玩家在不在線上
			if(loginSuccessAccounts.contains(accountID)){
				GUID playerGUID = entry.getValue();
				GUID sessionID = PlayerCommonInfoManager.getInstance().getSessionByPlayerGuid(playerGUID);
				
				//玩家不在線上，也要歸還
				if(sessionID == null){
					
					if(log.isWarnEnabled()){
						log.warn("["+ownModule.getModuleName()+"] may lose disconnect notify, accountID:"+accountID.toString()+", playerGUID:"+playerGUID.toString());
					}
					
					//加入觀察
					if(!resultAccountIDs.contains(accountID)){
						checkAcccounts.add(accountID);
					}
				}
			}
			//不在登入成功的列表時
			else{
				//不在這次的結果內加入觀察
				if(!resultAccountIDs.contains(accountID)){
					checkAcccounts.add(accountID);	
				}
			}
		}
		
		//對這些登入失敗的帳號，移除已借出
		for(GUID accountID : resultAccountIDs){
			lendOutAccountMap.remove(accountID);
			
			//如果有在登入成功的，其實是被檢查出來不在線上的，也要移除
			if(loginSuccessAccounts.contains(accountID)){
				loginSuccessAccounts.remove(accountID);
			}
		}
		
		if(log.isInfoEnabled()){
			log.info("["+ownModule.getModuleName()+"] check lend out accounts end, result:"+resultAccountIDs.size()+", check:"+checkAcccounts.size());
		}
		return resultAccountIDs;
	}
	
}
